/* Copyright (C) 2012  Chris Mueller <ruunsmail@googlemail.com>
 *
 * This file is part of the Liquid Programming Language
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "symbol.h"
#include "context.h"
#include "structures.h"
#include "map.h"
#include <assert.h>
#include <stdlib.h>

struct LqSymbol*   
lq_symbol_value_new(int line, struct LqNode* node)
{
	assert(node != 0);

	struct LqSymbol* symbol = malloc(sizeof(struct LqSymbol));
	symbol->line = line;
	symbol->kind = LQ_SYMBOL_VALUE;
	symbol->node = node;

	return symbol;
}


struct LqSymbol*   
lq_symbol_namespace_new(int line, struct LqNode* node)
{
	assert(node != 0);

	struct LqSymbol* symbol = malloc(sizeof(struct LqSymbol));
	symbol->line = line;
	symbol->kind = LQ_SYMBOL_NAMESPACE;
	symbol->node = node;

	return symbol;
}


struct LqSymbol*   
lq_symboltable_get(struct LqContext* context, const byte* identifier)
{
	assert(context != 0);
	assert(identifier != 0);

	size_t top_index = 0;
	struct LqMap* scope = lq_cast(struct LqMap*, lq_stack_top(context->symbols));
	struct LqSymbol* sym = 0;

	do {
		sym = lq_cast(struct LqSymbol*, lq_map_lookup(scope, identifier));
		scope = lq_stack_below(context->symbols, top_index++);
	} while(scope != 0 && sym == 0);

	return sym;
}


int                
lq_symboltable_add(struct LqContext* context, const byte* identifier, struct LqSymbol* symbol)
{
	assert(context != 0);
	assert(symbol != 0);

	struct LqMap* scope = lq_cast(struct LqMap*, lq_stack_top(context->symbols));

	assert(scope != 0);

	if(lq_map_lookup(scope, identifier) == 0) {
		lq_map_insert(scope, identifier, symbol);
		return TRUE;
	}

	return FALSE;
}


